package cn.jfast.plugin.wizards;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;

import cn.jfast.plugin.db.Column;
import cn.jfast.plugin.db.MySql;
import cn.jfast.plugin.db.Table;
import cn.jfast.plugin.generater.JfastConsole;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class AutoGenWizard extends Wizard implements INewWizard {
	
	private DataSourcePage dataSourcePage;
	private GenCodePathPage genCodePage;
	private ISelection selection;
	private DialogSettings dialogSettings;
	private static Configuration cfg = null;

	static {
		cfg = new Configuration();
		cfg.setClassForTemplateLoading(AutoGenWizard.class, "/template");
		cfg.setDefaultEncoding("UTF-8");
	}
	
	public AutoGenWizard() {
		super();
		dialogSettings = new DialogSettings("jfast");
		setNeedsProgressMonitor(true);
	}

	@Override
	public void createPageControls(Composite pageContainer) {
		super.createPageControls(pageContainer);
	}

	@Override
	public IDialogSettings getDialogSettings() {
		return dialogSettings;
	}

	@Override
	public void addPages() {
		dataSourcePage = new DataSourcePage(selection);
		addPage(dataSourcePage);
		genCodePage = new GenCodePathPage(selection);
		addPage(genCodePage);
	}

	@Override
	public boolean performFinish() {
		Map<String, Object> param = new HashMap<String, Object>();// 模板model
		Iterator<Table> ite = MySql.instance().getTables().iterator();
		final boolean[] gen = genCodePage.getGen();
		final String controllerPath = genCodePage.getActionPath().getText();
		final String servicePath = genCodePage.getServicePath().getText();
		final String daoPath = genCodePage.getDaoPath().getText();
		final String modelPath = genCodePage.getModelPath().getText();
		String pkg = "";
		String defaultPkg = null;
		if(null !=servicePath && !servicePath.equals("")){
			if (servicePath.indexOf("src/main/java") > 0) {
				defaultPkg = servicePath.substring(0,servicePath.indexOf("src/main/java") + 14);
			} else {
				defaultPkg = servicePath.substring(0,servicePath.indexOf("src/") + 4);
			}
		} else if(null !=controllerPath && !controllerPath.equals("")){
			if (controllerPath.indexOf("src/main/java") > 0) {
				defaultPkg = controllerPath.substring(0,controllerPath.indexOf("src/main/java") + 14);
			} else {
				defaultPkg = controllerPath.substring(0,controllerPath.indexOf("src/") + 4);
			}
		} else if(null !=daoPath && !daoPath.equals("")){
			if (daoPath.indexOf("src/main/java") > 0) {
				defaultPkg = daoPath.substring(0,daoPath.indexOf("src/main/java") + 14);
			} else {
				defaultPkg = daoPath.substring(0,daoPath.indexOf("src/") + 4);
			}
		} else if(null !=modelPath && !modelPath.equals("")){
			if (modelPath.indexOf("src/main/java") > 0) {
				defaultPkg = modelPath.substring(0,modelPath.indexOf("src/main/java") + 14);
			} else {
				defaultPkg = modelPath.substring(0,modelPath.indexOf("src/") + 4);
			}
		}
			
		if (gen[0]) {
			pkg = "";
			if (controllerPath.indexOf("src/main/java") > 0) {
				pkg = controllerPath.substring(controllerPath.indexOf("src/main/java") + 14).replace('/', '.');
			} else {
				pkg = controllerPath.substring(controllerPath.indexOf("src/") + 4).replace('/', '.');
			}
			param.put("controllerPkg",pkg);
		}
		if (gen[1] || gen[2]) {
			pkg = "";
			if (servicePath.indexOf("src/main/java") > 0) {
				pkg = servicePath.substring(servicePath.indexOf("src/main/java") + 14).replace('/', '.');
			} else {
				pkg = servicePath.substring(servicePath.indexOf("src/") + 4).replace('/', '.');
			}
			param.put("servicePkg",pkg);
		}
		if (gen[3] || gen[4]) {
			pkg = "";
			if (daoPath.indexOf("src/main/java") > 0) {
				pkg = daoPath.substring(daoPath.indexOf("src/main/java") + 14).replace('/', '.');
			} else {
				pkg = daoPath.substring(daoPath.indexOf("src/") + 4).replace('/', '.');
			}
			param.put("daoPkg",pkg);
		}
		if (gen[5]) {
			pkg = "";
			if (modelPath.indexOf("src/main/java") > 0) {
				pkg = modelPath.substring(modelPath.indexOf("src/main/java") + 14).replace('/', '.');
			} else {
				pkg = modelPath.substring(modelPath.indexOf("src/") + 4).replace('/', '.');
			}
			param.put("modelPkg",pkg);
		}
		// 数据表相关文件生成
		while(ite.hasNext()){
			Table table = ite.next();
			param.put("tableName", table.getTableName());
			param.put("primaryKey", table.getPrimaryKey());
			param.put("nickName", table.getNickName());
			param.put("columns", table.getColumn().values().toArray(new Column[]{}));
			param.put("primaryParamTemplate", table.getPrimaryParamTemplate());
			param.put("primaryKeyTemplate", table.getPrimaryKeyTemplate());
			param.put("primaryValueTemplate", table.getPrimaryValueTemplate());
			param.put("primaryPathRouteTemplate", table.getPrimaryPathRouteTemplate());
			String name = table.getNickName();
			final String module = name;
			final String controller = name + "Controller.java";
			final String service = name  + "Service.java";
			final String serviceimpl = name  + "ServiceImpl.java";
			final String dao = name  + "Dao.java";
			final String daoimpl = name + "DaoImpl.java";
			final String model = name + ".java";

			final Map<String, Object> o = param;

			IRunnableWithProgress op = new IRunnableWithProgress() {
				public void run(IProgressMonitor monitor) throws InvocationTargetException {
					try {
						if (gen[5]) {
							doFinish(module, model, "Model.ftl", modelPath, o, monitor);
						}
						if (gen[3]) {
							doFinish(module, dao, "Dao.ftl", daoPath, o, monitor);
						}
						if (gen[4]) {
							doFinish(module, daoimpl, "DaoImpl.ftl", daoPath, o, monitor);
						}
						if (gen[1]) {
							doFinish(module, service, "Service.ftl", servicePath, o, monitor);
						}
						if (gen[2]) {
							doFinish(module, serviceimpl, "ServiceImpl.ftl", servicePath, o, monitor);
						}
						if (gen[0]) {
							doFinish(module, controller, "Controller.ftl", controllerPath, o, monitor);
						}
					} catch (CoreException e) {
						e.printStackTrace();
					} finally {
						monitor.done();
					}
				}
			};
			try {
				getContainer().run(true, false, op);
			} catch (InterruptedException e) {
				e.printStackTrace();
				return false;
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				Throwable realException = e.getTargetException();
				MessageDialog.openError(getShell(), "Error", realException.getMessage());
				return false;
			}
		}
		
		// 更改jfast-config.xml配置文件
		final Map<String, Object> staticSetting = new HashMap<String, Object>();
		final String rootPath  = defaultPkg;
		staticSetting.put("jdbcUrl", MySql.instance().getDbUrl());
		staticSetting.put("jdbcUser", MySql.instance().getDbUser());
		staticSetting.put("jdbcPassword", MySql.instance().getDbPassword());
		IRunnableWithProgress op = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				try {
					if (gen[6]) {
						doFinish("", "jfast-config.xml", "Config.ftl",rootPath, staticSetting, monitor);
					}
				} catch (CoreException e) {
					e.printStackTrace();
				} finally {
					monitor.done();
				}
			}
		};
		try {
			getContainer().run(true, false, op);
		} catch (InterruptedException e) {
			e.printStackTrace();
			return false;
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			Throwable realException = e.getTargetException();
			MessageDialog.openError(getShell(), "Error", realException.getMessage());
			return false;
		}
		return true;
	}

	private void doFinish(String module, String fname, String template, String containerPath, Map<String, Object> param,
			IProgressMonitor mo) throws CoreException {
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		File tempFile = new File(root.getLocationURI().getPath()+containerPath);
		if(!tempFile.exists()){
			tempFile.mkdirs();
		}
		IResource resource = root.findMember(new Path(containerPath));
		if (!resource.exists() || !(resource instanceof IContainer)) {
			throwCoreException(containerPath + " not exists！");
		}
		IContainer cContiner = (IContainer) resource;// java文件路径
		mo.beginTask("generating file  ", 2);
		IFolder folder = cContiner.getFolder(new Path("/"));
		if (!folder.exists()) {// 如果不存在,创建包
			folder.create(true, true, mo);
		}
		final IFile file = folder.getFile(new Path(fname));
		try {
			JfastConsole.log("正在生成文件 ... " + fname);
			File tmpf = new File(root.getLocation().toOSString(), "tmp.txt");
			if (!tmpf.exists()) {
				tmpf.createNewFile();
			}
			exec(tmpf, template, param);

			InputStream stream = new FileInputStream(tmpf);
			if (file.exists()) {
				file.setContents(stream, true, true, mo);
			} else {
				file.create(stream, true, mo);
			}
			stream.close();
			tmpf.delete();
		} catch (Exception e) {
			throwCoreException(e.getMessage());
		}
		mo.worked(1);
		mo.worked(1);
	}

	private void exec(File target, String template, Map<String, Object> param) throws IOException, TemplateException {
		Template temp = cfg.getTemplate(template);
		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(target), "UTF-8"));
		temp.process(param, out);
		out.close();
	}

	private void throwCoreException(String message) throws CoreException {
		IStatus status = new Status(IStatus.ERROR, "cn.jfast.plugin", IStatus.OK, message, null);
		throw new CoreException(status);
	}

	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}
}